package com.cskaoyan.javase.oop1._1basic;

/**
 * 这里给出一个案例：
 * 创建学生对象，然后使用访问学生对象的属性，使用学生对象的行为。
 *
 * 首先想要创建对象,必须先定义创建对象的模型——类class
 * 类是抽象的，它是抽取出全体对象的共性属性和行为得到的
 * 那么于是我们需要开始去定义一个类
 *
 * 类的定义分为两个部分：
 *      1.类本身的定义
 *      2.类体的定义
 *
 * 类的定义：
 * 语法：
 * [各种修饰符] class 类名{
 *     // 类体
 * }
 * 各种修饰符主要就包括访问权限修饰符(public),其他修饰符,关于修饰符我们后面再说
 * 现在我们默认修饰符要么是public 要么就不写
 * 类有public和非public之分
 * 类名必须大驼峰式命名,然后最好有含义,不要乱起名字,尽量使用合法的英文单词，禁止使用拼音或者汉字
 *
 * 注意事项:
 *      1.一个java文件下,只有一个public class,但是可以有很多个非public class
 *          它们之间更具体来说是同包的关系
 *          同包下不允许存在同名class
 *      2.在实际开发中,一个Java文件往往里面就只有一个public class
 *          比较少见定义非public class
 *          我们上课时,为了方便演示代码,我们就会定义非public class
 *          一般情况下,我们会创建public class Demo作为一个测试的类
 *          然后在下面定义非public class用来作为创建对象的模板
 *      3.类是可以嵌套定义的,称之为内部类.但是我们现在不要这么做,因为你不懂内部类
 *          不会使用它
 *
 * 类体的定义
 * 类是模板,是对对象共性的抽取
 *
 * 1.抽取出全体对象属性的共性,加以描述
 *      在Java语法中,用"成员变量"来描述对象属性的共性
 *      成员变量: 指的是定义在成员位置的变量
 *          成员位置: 类体中,方法等局部位置之外,都是成员位置
 *      局部变量: 指的是定义在方法或者一个作用域内的变量,就是定义在局部位置的变量
 *          局部位置: 方法或者一个作用域内(代码块)
 *
 *      成员变量仍然是一个变量,它定义的语法是:
 *      [修饰符列表] 数据类型 变量名;
 *      成员变量的修饰符可以有很多,主要就是static,访问权限修饰符等等
 *      目前限于学习的进度,我们默认它没有修饰符列表,什么都不写
 *      变量名要遵循小驼峰式的命名规范,而且不要乱起名字,起名字要给它含义
 *      数据类型可以是基本数据类型,也可以是引用数据类型
 *
 * 2.抽取出全体对象行为的共性,加以描述
 * 行为其实就是一种操作,其实就是一种方法.
 * 在Java中,用成员方法来描述对象行为上的共性
 * 成员方法: 指的是定义在成员位置的,没有static修饰的方法,所以它的语法是:
 * [修饰符列表] 返回值类型 方法名(形参列表){
 *     // 方法体
 * }
 * 注: 修饰符列表中可以有访问权限修饰符(比如public),但是不能有static修饰
 * 语法其他部分和之前我们讲的方法,基本是一致的
 * 这里限于学习进度,我们默认修饰符列表是public
 *
 * 于是我们定义完了类和类体,类就定义完毕了,我们开始创建它的对象.
 *
 * 在能够创建这个类对象的位置中,创建对象的语法是:
 * 类名 对象名 = _1new 类名();
 * 类中定义的成员变量和成员方法只是一个抽象概念,具体只有创建了对象实例,才能够去访问它们.
 * 所以成员变量和成员方法其实都是对象的,存在对象,才能够访问.
 *
 * 创建对象后,怎么去访问对象的属性和行为呢?
 * 需要通过引用点,也就是对象名点去访问它们.
 *
 * 注意事项:
 *      1.成员变量,在类中的全局都是可以访问的,尤其是在成员方法中,可以任意访问的.
 *      但是要注意static方法不能直接访问成员变量
 *      static和非static是很明显的,static和static之间去访问,非static和非static之间互相访问
 *
 *      2.按照习惯我们先在类中定义成员变量，再在成员变量后面定义成员方法.
 *
 *      3.new关键字表示在堆上开辟空间创建对象，注意 new关键字一定会在堆上创建一个独立的对象。
 *
 * @since 10:53
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    // Demo类中写main方法 作为一个测试方法
    public static void main(String[] args) {
        // 创建Student对象
        // Student s2;
        // Variable 's2' might not have been initialized
        // System.out.println(s2);
        Student s = new Student();
        // 通过对象名点访问成员变量
        // null
        System.out.println(s.name);
        // 0
        System.out.println(s.stuId);
        // 0.0
        System.out.println(s.score);
        // 0
        System.out.println(s.age);

        // 通过对象名点来给成员变量赋值
        s.age = 10;
        System.out.println(s.age);

        // 通过对象名点来调用方法
        s.study();
        s.eat(1000000);

        // 直接输出对象名,相当于打印数组名
        /*
            com.cskaoyan.javase.oop1._1basic.Student@1540e19d
            在默认情况下,直接打印某个类的对象,会在控制台输出:
              com.cskaoyan.javase.oop1._1basic.Student 这是全限定类名
              @1540e19d是一个十六进制地址值,是堆上对象的地址
              所以对象名其实就是引用,里面装的是对象的地址
         */
        System.out.println(s);
        Student s2 = new Student();
        System.out.println(s2);

        String[] arr = new String[3];
        System.out.println(arr);

        // Teacher override = _1new Teacher();
    }

    // 不要嵌套定义内部类,你不知道语法不会使用
    // static class Teacher {
    // }

}


// 定义非public class 学生类
class Student {

    // 抽取学生对象的共性属性,然后定义成员变量
    String name;
    int stuId;
    double score;
    int age;

    // 抽取学生对象的共性行为,然后定义成员方法
    public void study() {
        System.out.println(score);
        System.out.println("好好学习,天天向上");
    }

    // public static void test(){
    //     System.out.println(age);
    // }

    public void eat(double money) {
        if (money > 10000) {
            System.out.println("我要吃山珍海味!");
            return;
        }
        if (money > 5000) {
            System.out.println("我要和鸡汤!");
            return;
        }
        if (money > 1000) {
            System.out.println("吃食堂!");
            return;
        }
        if (money < 0) {
            System.out.println("吃土!");
        }
    }

}